/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.mocamorena.persistence.dao.impl;

import br.com.mocamorena.exception.PersistenciaException;
import br.com.mocamorena.model.Endereco;
import br.com.mocamorena.model.constant.UnidadeFederativa;
import br.com.mocamorena.persistence.GerenciadorDeConexao;
import br.com.mocamorena.persistence.dao.EnderecoDao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Diego
 */
public class EnderecoDaoImpl implements EnderecoDao {

    private Connection conn;
    private PreparedStatement pr;
    private ResultSet rs;

    @Override
    public boolean inserir(Endereco endereco) throws PersistenciaException {
        if (endereco == null) {
            throw new PersistenciaException("Não foi informado o endereço a cadastrar.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("INSERT INTO ENDERECO(ID, CEP, LOGRADOURO, BAIRRO, CIDADE, ESTADO) VALUES(NULL, ?, ?, ?, ?, ?);",
                    Statement.RETURN_GENERATED_KEYS);
            pr.setString(1, endereco.getCep());
            pr.setString(2, endereco.getLogradouro());
            pr.setString(3, endereco.getBairro());
            pr.setString(4, endereco.getCidade());
            pr.setString(5, endereco.getUf().name());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
                rs = pr.getGeneratedKeys();
                rs.first();
                long id = rs.getLong(1);
                endereco.setId(id);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível cadastrar o endereço.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return sucesso;
    }

    @Override
    public boolean atualizar(Endereco endereco) throws PersistenciaException {
        if (endereco == null) {
            throw new PersistenciaException("Não foi informado o endereço a atualizar.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("UPDATE ENDERECO SET CEP=?, LOGRADOURO=?, BAIRRO=?, CIDADE=?, ESTADO=? WHERE ID=?");
            pr.setString(1, endereco.getCep());
            pr.setString(2, endereco.getLogradouro());
            pr.setString(3, endereco.getBairro());
            pr.setString(4, endereco.getCidade());
            pr.setString(5, endereco.getUf().name());
            pr.setLong(6, endereco.getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível atualizar o endereço.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
        return sucesso;
    }

    @Override
    public boolean excluir(Endereco endereco) throws PersistenciaException {
        if (endereco == null) {
            throw new PersistenciaException("Não foi informado o endereço a excluir.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("DELETE FROM ENDERECO WHERE ID=?");
            pr.setLong(1, endereco.getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível excluir o endereço.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
        return sucesso;
    }

    @Override
    public List<Endereco> listarPeloCep(String cep) throws PersistenciaException {
        List<Endereco> lista = new ArrayList<Endereco>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT ID, CEP, LOGRADOURO, BAIRRO, CIDADE, ESTADO FROM ENDERECO WHERE CEP=?");
            pr.setString(1, cep);
            rs = pr.executeQuery();
            while (rs.next()) {
                Endereco endereco = this.criarEndereco(rs);
                lista.add(endereco);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar o endereço pelo cep.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    @Override
    public List<Endereco> listarPeloLogradouro(String logradouro) throws PersistenciaException {
        List<Endereco> lista = new ArrayList<Endereco>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT ID, CEP, LOGRADOURO, BAIRRO, CIDADE, ESTADO FROM ENDERECO WHERE LOGRADOURO LIKE ? ORDER BY LOGRADOURO");
            pr.setString(1, "%" + logradouro + "%");
            rs = pr.executeQuery();
            while (rs.next()) {
                Endereco endereco = this.criarEndereco(rs);
                lista.add(endereco);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar os endereços pelo logradouro.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    @Override
    public List<Endereco> listarPeloBairro(String bairro) throws PersistenciaException {
        List<Endereco> lista = new ArrayList<Endereco>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT ID, CEP, LOGRADOURO, BAIRRO, CIDADE, ESTADO FROM ENDERECO WHERE BAIRRO LIKE ? ORDER BY LOGRADOURO");
            pr.setString(1, "%" + bairro + "%");
            rs = pr.executeQuery();
            while (rs.next()) {
                Endereco endereco = this.criarEndereco(rs);
                lista.add(endereco);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar os endereços pelo bairro.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    private Endereco criarEndereco(ResultSet rs) throws PersistenciaException {
        Endereco endereco = null;
        try {
            endereco = new Endereco(rs.getLong("ID"));
            endereco.setCep(rs.getString("CEP"));
            endereco.setLogradouro(rs.getString("LOGRADOURO"));
            endereco.setBairro(rs.getString("BAIRRO"));
            endereco.setCidade(rs.getString("CIDADE"));
            endereco.setUf(UnidadeFederativa.valueOf(rs.getString("ESTADO")));
        } catch (SQLException sqlex) {
            StringBuilder msg = new StringBuilder("Não foi possível obter os dados do endereço.");
            msg.append("\nMotivo: ").append(sqlex.getMessage());
            throw new PersistenciaException(msg.toString());
        }
        return endereco;
    }
}
